package neuralModel.neuron;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;

import neuralModel.activationFunction.IActivationFunction;

public class Neuron implements INeuron, Serializable
{
	/**
	 * 
	 */
  private static final long serialVersionUID = -3490646444120489915L;
  
	private String name;
	private int layer;

	private double inducedLocalField;
	private double outputValue;

	private IActivationFunction activationFunction;

	private List<ISignal> inputSignals;
	private List<ISignal> outputSignals;

	public Neuron()
	{
	}

	public Neuron(String name, IActivationFunction activationFunction)
	{
		this.name = name;
		this.activationFunction = activationFunction;
		inducedLocalField = 0;

		inputSignals = new ArrayList<ISignal>();
		outputSignals = new ArrayList<ISignal>();
	}

	@Override
	public String getName()
	{
		return name;
	}

	@Override
	public int getNetworkLayer()
	{
		return layer;
	}

	@Override
	public void setNetworkLayer(int layer)
	{
		this.layer = layer;
	}

	@Override
	public void addInputSignal(ISignal signal)
	{
		inputSignals.add(signal);
	}

	@Override
	public void addOutputSignal(ISignal signal)
	{
		outputSignals.add(signal);
	}

	@Override
	public List<ISignal> getInputSignalList()
	{
		return inputSignals;
	}

	@Override
	public List<ISignal> getOutputSignalList()
	{
		return outputSignals;
	}

	@Override
	public double getInducedLocalField()
	{
		return inducedLocalField;
	}

	@Override
	public void setInducedLocalField(double inducedLocalField)
	{
		this.inducedLocalField = inducedLocalField;
	}

	@Override
	public IActivationFunction getActivationFunction()
	{
		return activationFunction;
	}

	@Override
	public void setActivationFunction(IActivationFunction activationFunction)
	{
		this.activationFunction = activationFunction;
	}

	@Override
	public double getOutputValue()
	{
		return outputValue;
	}

	@Override
	public void setOutputValue(double outputValue)
	{
		this.outputValue = outputValue;
	}

	@Override
	public void updateInducedLocalField()
	{
		inducedLocalField = 0;
		for (ISignal signal : inputSignals)
		{
			inducedLocalField += signal.getWeightedValue();
		}
	}

	@Override
	public void updateOutputValue()
	{
		outputValue = activationFunction.calculateOutputValue(inducedLocalField);
	}

	@Override
	public void driveOutputValue()
	{
		for (ISignal signal : outputSignals)
			signal.setSignalValue(outputValue);
	}

	@Override
	public String toString()
	{
		return name;
	}

	@Override
	public void setName(String name)
	{
		this.name = name;
	}

	@Override
	public void setInputSignalList(List<ISignal> inputList)
	{
		this.inputSignals = inputList;
	}

	@Override
	public void setOutputSignalList(List<ISignal> outputList)
	{
		this.outputSignals = outputList;
	}

}
